#region Namespaces

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;

#endregion

namespace Utilities.Grammar
{

    /*

How to use ConstantsGenerator:

** Prerequisite
Make sure your GOLD Parser Builder installation has the "Epi Info.pgt" template file in its Templates folder.

** Steps
1.  Compile the contents of EpiInfoGrammar.txt using GOLD Parser Builder to generate a CGT file.
2.  Click on "Tools -> Create Skeleton Program" in GOLD Parser Builder.
3.  Choose "Epi Info" as the template.
4.  Click "Create" to generate an XML file.
6.  Run ConstantsGenerator.
7.  Click "Generate Constants".
8.  Select the XML file generated in Step 4 to generate the constants.

    *** The constants have now been generated***

9.  Replace the source controlled "EpiInfoGrammar.cgt" file with the one generated in Step 1.
10. Replace the contents of "ParserConstants.cs" with the constants generated in Step 8.

     */

    /// <summary>
    /// Generates grammar constants that can be added to ParserConstants.cs
    /// </summary>
    public partial class ConstantsGenerator : Form
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public ConstantsGenerator()
        {
            InitializeComponent();
        }

        private void btnProcessXml_Click(object sender, EventArgs e)
        {
            DataSet ds = new DataSet();
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "GOLD Parser XML Files|*.xml";
            dialog.Title = "Specify XML file generated by GOLD Parser Builder using the Epi Info Template";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                ds.ReadXml(dialog.FileName);
                if (ds.Tables.Count > 0)
                {
                    textBox1.AppendText(ProcessSymbols(ds));
                    textBox1.AppendText(Environment.NewLine);
                    textBox1.AppendText(ProcessRules(ds));
                }
                else
                {
                    MessageBox.Show("Invalid Grammar XML");
                }
            }
        }

        private string ProcessSymbols(DataSet ds)
        {
            List<string> symbols = new List<string>();
            string symbol;
            StringBuilder symbolSectionBuilder = new StringBuilder();
            symbolSectionBuilder.AppendLine("public enum Symbols");
            symbolSectionBuilder.AppendLine("{");
            foreach (DataRow row in ds.Tables[1].Rows)
            {
                // Add XML Comment in the form /// <summary>STATISTICS Symbol</summary>
                symbol = row["id"].ToString();
                symbolSectionBuilder.AppendLine(GetComment(symbol.Replace("SYMBOL_", String.Empty).Replace('_', ' ') + " Symbol"));
                symbolSectionBuilder.AppendLine(symbol + ",");
            }
            symbolSectionBuilder.AppendLine("}");
            return symbolSectionBuilder.ToString();
        }

        private string ProcessRules(DataSet ds)
        {
            List<string> rules = new List<string>();
            StringBuilder ruleSectionBuilder = new StringBuilder();
            ruleSectionBuilder.AppendLine("public enum Rules");
            ruleSectionBuilder.AppendLine("{");
            foreach (DataRow row in ds.Tables[3].Rows)
            {
                string[] splitArray = row["id"].ToString().Split('_');
                string lastPart = splitArray[splitArray.Length - 1];
                int indexOfNumber = lastPart.IndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' });
                int ruleCount = 0;
                if (indexOfNumber >= 0)
                {
                    int temp;
                    if (int.TryParse(lastPart.Substring(indexOfNumber, lastPart.Length - indexOfNumber), out temp))
                    {
                        ruleCount = int.Parse(lastPart.Substring(indexOfNumber, lastPart.Length - indexOfNumber));
                    }
                }
                string description = row["description"].ToString();
                string ruleName = description.ToString().Substring(1, description.IndexOf('>') - 1).Replace(' ', '_');
                if (ruleCount > 0)
                {
                    ruleName += ruleCount.ToString();
                }
                if (rules.Contains(ruleName))
                {
                    int altCounter = 2;
                    while (rules.Contains(ruleName + altCounter.ToString()))
                    {
                        altCounter++;
                    }
                    ruleName += altCounter.ToString();
                }
                rules.Add(ruleName);
                ruleSectionBuilder.AppendLine(GetComment(description));
                ruleSectionBuilder.AppendLine(ruleName + ",");
            }
            ruleSectionBuilder.AppendLine("}");
            return ruleSectionBuilder.ToString();
        }

        private string GetComment(string description)
        {
            XmlDocument comment = new XmlDocument();
            XmlElement element = comment.CreateElement("summary");
            element.InnerText = description;
            System.IO.StringWriter sw = new System.IO.StringWriter();
            XmlTextWriter tw = new XmlTextWriter(sw);
            element.WriteTo(tw);
            return "/// " + sw.ToString();
        }

    }
}